Modern day compilers create data structures such as, for example, a control flow graph to represent the program instructions to be compiled and/or optimized by the compiler. The control flow graph includes nodes and directed edges. Each node represents a basic block (e.g., a straight-line (i.e., sequential) segment of program instructions without any jumps or jump targets in the middle of the segment). The directed edges of the control flow graph represent jumps and/or transitions from a first basic block to a second basic block in the program instructions. Jumps may be a function call, a conditional statement, etc.
Typical compilers will create a control flow graph using a conservative approach in the presence of instructions used to bypass standard function call and return procedures (e.g., return instructions) such as a setjmp and/or a longjmp instruction in the C programming language. The setjmp and longjmp instructions are used in pairs to enable repeat execution of code with the same program state. More specifically, the setjmp instruction is used to save a runtime environment (e.g., values of variables, object values, stack pointer value, and register values) in a setjmp buffer. The longjmp instruction is used to restore the runtime environment saved in the setjmp buffer by the corresponding setjmp instruction and to return control to the instruction immediately following the setjmp instruction such that the instruction following the setjmp instruction executes in the restored runtime environment. The argument of a longjmp instruction is a pointer which references a setjmp buffer that stores the runtime environment the longjmp instruction is to restore. (The setjmp/longjmp approach is, in some respects, more useful then using a traditional goto statement. For instance, a goto statement is limited to affecting a local jump whereas a longjmp instruction may be used for a non-local jump.)
The conservative approach used by typical compilers generally assumes that any function call reachable from a setjmp instruction may return control to the program instruction following the setjmp instruction. In other words, the conservative approach assumes: (1) that every function that may be executed after a setjmp instruction has been executed may contain a longjmp instruction, and (2) the function may return control to the basic block following the setjmp instruction (e.g., a successor block). This conservative approach results in extraneous directed edges in the control flow graph. The extraneous directed edges may have an effect on the amount of optimization a compiler may perform.